/*
 * Copyright (c) 2024 iSoftStone Education Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <stdbool.h>

#include "los_task.h"
#include "ohos_init.h"
#include "cmsis_os.h"
#include "config_network.h"
#include "smart_home.h"
#include "smart_home_event.h"
#include "su_03t.h"
#include "iot.h"
#include "lcd.h"
#include "picture.h"
#include "adc_key.h"
#include "oc_mqtt.h"




#include"wifi_tcp_example.h"

#define ROUTE_SSID      "Abcd"          // WiFi账号
#define ROUTE_PASSWORD "panyusen18747668165"       // WiFi密码

#define MSG_QUEUE_LENGTH                                16
#define BUFFER_LEN                                      50

 int fmq_flag=0;
 float qqm=0;
 double q_temp=0;
 double q_humi=0;
 double q_lum=0;

short q_x=123;
short q_y=231;
short q_z=122;



////////////////////////////////////
///////新增代码start/////


/////蜂鸣器start

#include "iot_errno.h"
#include "iot_pwm.h"

/* 蜂鸣器对应PWM */
#define BEEP_PORT EPWMDEV_PWM5_M0

/***************************************************************
* 函数名称: beep_process
* 说    明: 控制蜂鸣器线程函数
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void beep_process()
{
    printf("有毒有毒！！！！/n");
    unsigned int ret;
    unsigned int duty = 10;

    /* 初始化PWM */
    ret = IoTPwmInit(BEEP_PORT);
    if (ret != 0) {
        printf("IoTPwmInit failed(%d)\n", BEEP_PORT);
    }

    while (1)
    {

        if(fmq_flag==1){
            

        
        printf("===========================\n");

        printf("PWM(%d) Start\n", BEEP_PORT);
        printf("duty: %d\r\n", duty);
        /* 开启PWM */
        ret = IoTPwmStart(BEEP_PORT, duty, 1000);
        if (ret != 0) {
            printf("IoTPwmStart failed(%d)\n");
            continue;
        }
        
        LOS_Msleep(2000);

        /* 关闭PWM */
        ret = IoTPwmStop(BEEP_PORT);
        if (ret != 0) {
            printf("IoTPwmStart failed(%d)\n");
            continue;
        }

        LOS_Msleep(2000);
        }
         LOS_Msleep(1000);
         //printf("\n蜂鸣器线程：%d",fmq_flag);
        //占空比渐渐增大
        // duty += 10;
        // if (duty == 100)
        // {
        //     duty = 10;
        // }
    }
}


//////蜂鸣器end



/////气体传感器start
#include "mq2.h"

/***************************************************************
 * 函数名称: gas_sensor_process
 * 说    明: ADC采集循环任务
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
int fq=0;
float gas_sensor_process() 
{
  float ppm;

  /* 初始化mq2设备 */
//   if(fq==0){
//     printf("气体传感器初始化\n");
//   mq2_dev_init();
//   LOS_Msleep(1000);
//   /* 传感器校准 */
//   mq2_ppm_calibration();
//   fq=1;

//   }
  
  

  //while (1) 
  //{
    printf("***************Gas Sensor Example*************\r\n");
    /*获取电压值*/
    ppm = get_mq2_ppm();
    printf("ppm: %.3f \r\n", ppm);

    /* 睡眠1秒 */
    //LOS_Msleep(1000);
 // }
 return ppm;
}



//////气体传感器end


///加速度传感器start
#include "mpu6050.h"

/***************************************************************
 * 函数名称: mpu6050_proress
 * 说    明: mpu6050实验
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
int fj=0;
void mpu6050_proress(short *arg)
{
    short mpu6050_data[3] = {0};

if(fj==0){
mpu6050_init();
fj=1;
}
    

    
        printf("************ Mpu6050 Process ************\n");

        mpu6050_read_data(mpu6050_data);

        printf("x %d y %d z %d \r\n", mpu6050_data[0], mpu6050_data[1], mpu6050_data[2]);

        printf("\r\n");
        arg=mpu6050_data;

    
}



////加速度end




#define CLIENT_ID                       "67628922ef99673c8ad6f033_os11_0_0_2024121814"
#define USERNAME                        "67628922ef99673c8ad6f033_os11"
#define PASSWORD                        "cc6653a0804182b8a3d6dba38ec4ce078701a2bfaf5b05fb80e60325c6d1a29a"

//装载上传到华为云的数据结构体
typedef struct
{
    // void *x;
    // int y;
    // int z;
    float temperature;
    float humidity;
    float light;
    unsigned int tilt_status;
} sc_report_t;

typedef struct
{
    en_msg_type_t msg_type;
    sc_report_t report;
} sc_msg_t;

//队列ID
static unsigned int m_sc_msg_queue;


/***************************************************************
* 函数名称: sc_deal_report_msg
* 说    明: 上报智慧井盖模块数据到华为云上
* 参    数: report：智慧农业上报消息指针
* 返 回 值: 无
***************************************************************/
void sc_deal_report_msg(sc_report_t *report)
{
    oc_mqtt_profile_service_t service;
    oc_mqtt_profile_kv_t temperature;
     oc_mqtt_profile_kv_t humidity;
      oc_mqtt_profile_kv_t light;
 

    service.event_time = NULL;
    service.service_id = "os";
    service.service_property = &temperature;
    service.nxt = NULL;

    temperature.key = "temperature";
    
    char st[20];
    snprintf(st,sizeof(st),"%.1f",report->temperature);

    temperature.value =  st;//&report->t;//*(&report->t);
    temperature.type =EN_OC_MQTT_PROFILE_VALUE_STRING; 
    //EN_OC_MQTT_PROFILE_VALUE_STRING;
   //  x.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    temperature.nxt = &humidity;

    //humidity
    humidity.key = "humidity";
    
    char st1[20];
    snprintf(st1,sizeof(st1),"%.1f",report->humidity);

    humidity.value =  st1;//&report->t;//*(&report->t);
    humidity.type =EN_OC_MQTT_PROFILE_VALUE_STRING; 
    humidity.nxt = &light;

    //light
    light.key = "light";
    char st2[20];
    snprintf(st2,sizeof(st2),"%.1f",report->light);

    light.value =  st2;//&report->t;//*(&report->t);
    light.type =EN_OC_MQTT_PROFILE_VALUE_STRING; 
    light.nxt = NULL;





    oc_mqtt_profile_propertyreport(USERNAME, &service);
    return;
}

/***************************************************************
* 函数名称: iot_cloud_sc_thread
* 说    明: 华为云消息线程
* 参    数: 无
* 返 回 值: 无
***************************************************************/
int iot_cloud_sc_thread()
{
    // uint8_t hwaddr[6]  = {0x10, 0xdc, 0xb6, 0x90, 0x00, 0x00};
    // sc_msg_t *app_msg = NULL;
     unsigned int addr;
     int ret;

    // FlashInit(); 
    // VendorSet(VENDOR_ID_MAC,               hwaddr,         6);  // 多人同时做该实验，请修改各自不同的WiFi MAC地址
    // VendorSet(VENDOR_ID_WIFI_ROUTE_SSID,   ROUTE_SSID,     sizeof(ROUTE_SSID));
    // VendorSet(VENDOR_ID_WIFI_ROUTE_PASSWD, ROUTE_PASSWORD, sizeof(ROUTE_PASSWORD));
    // SetWifiModeOn();
    
  

    // device_info_init(CLIENT_ID, USERNAME, PASSWORD);
      // ret = oc_mqtt_init();
    // if (ret != LOS_OK)
    // {
    //     printf("oc_mqtt_init fail ret:%d\n", ret);
    // }

    while (1)
    {
        ret = LOS_QueueRead(m_sc_msg_queue, (void *)&addr, BUFFER_LEN, LOS_WAIT_FOREVER);
        // if (ret == LOS_OK)
        // {
        //     printf("有数据/n");
        //     app_msg = addr;
        //     switch (app_msg->msg_type)
        //     {
        //         case en_msg_report:
        //             sc_deal_report_msg(&app_msg->report);
        //             printf("-------updata data----------------%f\n",app_msg->report.temperature);
        //             LOS_Msleep(1000);
        //             break;
        //         default:
        //             break;
        //     }
        //     free(app_msg);
        //     app_msg = NULL;
        // }
        // else
        // {
        //     printf("wu数据/n");
        //     LOS_Msleep(100);
        // }
        LOS_Msleep(100);
    }
}






//////新增代码end///////
////////////////////////////////



/***************************************************************
 * 函数名称: iot_thread
 * 说    明: iot线程
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void iot_thread(void *args) {
  uint8_t mac_address[12] = {0x00, 0xdc, 0xb6, 0x90, 0x01, 0x00,0};

  char ssid[32]=ROUTE_SSID;
  char password[32]=ROUTE_PASSWORD;
  char mac_addr[32]={0};


  FlashInit();
  VendorSet(VENDOR_ID_WIFI_MODE, "STA", 3); // 配置为Wifi STA模式
  VendorSet(VENDOR_ID_MAC, mac_address, 6); // 多人同时做该实验，请修改各自不同的WiFi MAC地址
  VendorSet(VENDOR_ID_WIFI_ROUTE_SSID, ssid, sizeof(ssid));
  VendorSet(VENDOR_ID_WIFI_ROUTE_PASSWD, password,sizeof(password));


reconnect:
  SetWifiModeOff();
  int ret = SetWifiModeOn();
  if(ret != 0){
    printf("wifi connect failed,please check wifi config and the AP!\n");
    return;
  }
  //mqtt_init();

  while (1) {
    if (!wait_message()) {
      goto reconnect;
    }
    LOS_Msleep(1);
  }
}


/***************************************************************
 * 函数名称: smart_home_thread
 * 说    明: 智慧家居主线程
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/


void smart_home_thread(void *arg)
{
    extern int fmq_flag; 
    extern float qqm;
    double *data_ptr = NULL;

    extern double q_temp;
    extern double q_humi;
    extern double q_lum;

    extern short q_x;
    extern short q_y;
    extern short q_z;

    double illumination_range = 50.0;
    double temperature_range = 35.0;
    double humidity_range = 80.0;

    e_iot_data iot_data = {0};

    i2c_dev_init();
    lcd_dev_init();
    motor_dev_init();
    light_dev_init();
    su03t_init();

    // lcd_load_ui();
    lcd_show_ui();

    while(1)
    {
        event_info_t event_info = {0};
        //等待事件触发,如有触发,则立即处理对应事件,如未等到,则执行默认的代码逻辑,更新屏幕
        int ret = smart_home_event_wait(&event_info,3000);
        if(ret == LOS_OK){
            //收到指令
            printf("event recv %d ,%d\n",event_info.event,event_info.data.iot_data);
            switch (event_info.event)
            {
                case event_key_press:
                    smart_home_key_process(event_info.data.key_no);
                    
                    break;
                case event_iot_cmd:
                    smart_home_iot_cmd_process(event_info.data.iot_data);
                    break;
                case event_su03t:
                    smart_home_su03t_cmd_process(event_info.data.su03t_data);
                    break;
               default:break;
            }

        }

        double temp,humi,lum;

        //读取温湿度  
        sht30_read_data(&temp,&humi);
        //读取光照强度
        bh1750_read_data(&lum);
        //读取气体浓度
        float ppm=gas_sensor_process();
        qqm=ppm;
        printf("气体浓度:%f\n",ppm);
        q_humi=humi;
        q_lum=lum;
        q_temp=temp;
        if (ppm>1000)
        {
            fmq_flag=1; 
           // beep_process();
        }else
        {
            fmq_flag=0;
        }
        
        
        //读取加速度
        // short mp[3]={0,0,0};
        // mpu6050_proress(mp);
        //  printf("加速度:%f\n",mp[0]);
         short mpu6050_data[3] = {0};
        // int fj=0;
        // if(fj==0){
        //       mpu6050_init();
        //       fj=1;
        //         }
       
    
        printf("************ Mpu6050 Process ************\n");
        mpu6050_read_data(mpu6050_data);

        printf("x: %d y: %d z: %d \r\n", mpu6050_data[0], mpu6050_data[1], mpu6050_data[2]);

        q_x=mpu6050_data[0];
        q_y=mpu6050_data[1];
        q_z=mpu6050_data[2];



        
        //将温湿度和光照显示在屏幕上
        lcd_set_illumination(lum);
        lcd_set_temperature(temp);
        lcd_set_humidity(humi);
        printf("----------wendu:%f",temp);
        printf("---温度-------wendu:%f",temp);

        /////////////把数据写入队列
        LOS_Msleep(100);
        sc_msg_t *app_msg=NULL;
        //每次都开辟内存过于浪费！！！！！！！
        app_msg = malloc(sizeof(sc_msg_t));
         if (app_msg != NULL)
        {
        
            app_msg->msg_type = en_msg_report;
           // char str[700]="";
            // char sp[4];
            
            
          //  int y=0;
            // for(;y<176;y++){
            // sprintf(sp, "%d", m_uart_recv_fifo.buffer[y]);
            // strcat(str,sp);
            // sprintf(sp, "%c", 97);
            // strcat(str,sp);
            
            //         }
            // printf("%d\n",strlen(str));
            // printf("%s\n",str);
            
            app_msg->report.light = lum;
            app_msg->report.humidity=humi;
            app_msg->report.temperature=temp;
            app_msg->report.tilt_status = 1;
            if (LOS_QueueWrite(m_sc_msg_queue, (void *)app_msg, sizeof(sc_msg_t), LOS_WAIT_FOREVER) != LOS_OK)
            {
                printf("%s LOS_QueueWrite fail\n", __func__);
                free(app_msg);
            }
        }

        /////////////////////////////写入end





        if (mqtt_is_connected()) 
        {
            // 发送iot数据
            iot_data.illumination = lum;
            iot_data.temperature = temp;
            iot_data.humidity = humi;
            iot_data.light_state = get_light_state();
            iot_data.motor_state = get_motor_state();
            // iot_data.auto_state = auto_state;
            send_msg_to_mqtt(&iot_data);

            lcd_set_network_state(true);
        }else{  
            lcd_set_network_state(false);
        }

        lcd_show_ui();
    }
}

/***************************************************************
 * 函数名称: device_read_thraed
 * 说    明: 设备读取线程
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
// void device_read_thraed(void *arg)
// {
//     double read_data[3] = {0};

//     i2c_dev_init();

//     while(1)
//     {
//         bh1750_read_data(&read_data[0]);
//         sht30_read_data(&read_data[1]);
//         LOS_QueueWrite(m_msg_queue, (void *)&read_data, sizeof(read_data), LOS_WAIT_FOREVER);
//         LOS_QueueWrite(m_su03_msg_queue, (void *)&read_data, sizeof(read_data), LOS_WAIT_FOREVER);
//         LOS_Msleep(500);
//     }
// }


#define GPIO_BODY_INDUCTION GPIO0_PA3
#include "iot_gpio.h"

/***************************************************************
 * 函数名称: body_induction_get_state
 * 说    明: 获取人体感应状态
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void body_induction_get_state(bool *dat)
{
    IotGpioValue value = IOT_GPIO_VALUE0;

    IoTGpioGetInputVal(GPIO_BODY_INDUCTION, &value);

    if (value) 
    {
        *dat = true;
    }
    else
    {
        *dat = false;
    }
}

/***************************************************************
 * 函数名称: body_induction_dev_init
 * 说    明: 人体感应传感器初始化
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void body_induction_dev_init(void)
{
    IoTGpioInit(GPIO_BODY_INDUCTION);
    IoTGpioSetDir(GPIO_BODY_INDUCTION, IOT_GPIO_DIR_IN);
}


/***************************************************************
 * 函数名称: device_read_thraed
 * 说    明: 设备读取线程
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void device_read_thraed(void *arg)
{
    double read_data[2] = {0};

    body_induction_dev_init();
    int body_count_1=0;
    int body_count_0=0;

    while(1)
    {
      
        body_induction_get_state((bool *)&read_data[0]);
        if((bool)read_data[0]){
             //printf("\n---------有人-------\n");

             body_count_1++;
             if(body_count_1>100){
                    printf("\n---------停顿很久-------\n");
                }
            if(body_count_1>40){
                printf("\n---------确认吗？-------\n");
                motor_set_state(true);

            }
             body_count_0=0;


        }else{
            body_count_0++;
            if(body_count_1>0 && body_count_0>10){
                printf("\n-------计数%d---------\n",body_count_1);
                if(body_count_1>50){
                    printf("\n---------确认-------\n");
                     an0k();
                     motor_set_state(false);
                }else{
                     printf("\n---------挥手-------\n");
                     lcd_menu_selected_move_right();
                      motor_set_state(false);
                }
                body_count_1=0;

            }
            //printf("\n---------无人-------\n");
           
        }
       
        LOS_Msleep(100);
    }
}


/***************************************************************
 * 函数名称: iot_smart_hone_example
 * 说    明: 开机自启动调用函数
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void iot_smart_home_example()
{
    unsigned int thread_id_1;
    unsigned int thread_id_2;
    unsigned int thread_id_3;
    unsigned int thread_id_4;
    unsigned int thread_id_5;
    unsigned int thread_id_6;
    TSK_INIT_PARAM_S task_1 = {0};
    TSK_INIT_PARAM_S task_2 = {0};
    TSK_INIT_PARAM_S task_3 = {0};
    TSK_INIT_PARAM_S task_4 = {0};
    TSK_INIT_PARAM_S task_5 = {0};
    TSK_INIT_PARAM_S task_6 = {0};
    unsigned int ret = LOS_OK;
    
    smart_home_event_init();

    mpu6050_init();

      mq2_dev_init();
    LOS_Msleep(1000);
  /* 传感器校准 */
  mq2_ppm_calibration();
    
    // ret = LOS_QueueCreate("su03_queue", MSG_QUEUE_LENGTH, &m_su03_msg_queue, 0, BUFFER_LEN);
    // if (ret != LOS_OK)
    // {
    //     printf("Falied to create Message Queue ret:0x%x\n", ret);
    //     return;
    // }


   //创建队列
    ret = LOS_QueueCreate("queue", MSG_QUEUE_LENGTH, &m_sc_msg_queue, 0, BUFFER_LEN);
    if (ret != LOS_OK)
    {
        printf("Falied to create Message Queue ret:0x%x\n", ret);
        return;
    }

    task_1.pfnTaskEntry = (TSK_ENTRY_FUNC)smart_home_thread;
    task_1.uwStackSize = 2048;
    task_1.pcName = "smart hone thread";
    task_1.usTaskPrio = 24;
    
    ret = LOS_TaskCreate(&thread_id_1, &task_1);
    if (ret != LOS_OK)
    {
        printf("Falied to create task ret:0x%x\n", ret);
        return;
    }

    task_2.pfnTaskEntry = (TSK_ENTRY_FUNC)adc_key_thread;
    task_2.uwStackSize = 2048;
    task_2.pcName = "key thread";
    task_2.usTaskPrio = 24;
    ret = LOS_TaskCreate(&thread_id_2, &task_2);
    if (ret != LOS_OK)
    {
        printf("Falied to create task ret:0x%x\n", ret);
        return;
    }

    task_3.pfnTaskEntry = (TSK_ENTRY_FUNC)iot_cloud_sc_thread;//iot_thread;
   // task_3.uwStackSize = 20480*5;
   task_3.uwStackSize = 2048;
    task_3.pcName = "iot thread";
    task_3.usTaskPrio = 24;
    ret = LOS_TaskCreate(&thread_id_3, &task_3);
    if (ret != LOS_OK)
    {
        printf("Falied to create task ret:0x%x\n", ret);
        return;
    }

//蜂鸣器线程
    task_4.pfnTaskEntry = (TSK_ENTRY_FUNC)beep_process;
    task_4.uwStackSize = 2048;
    task_4.pcName = "beep_process";
    task_4.usTaskPrio = 24;
    ret = LOS_TaskCreate(&thread_id_4, &task_4);
    if (ret != LOS_OK)
    {
        printf("Falied to create beep_process ret:0x%x\n", ret);
        return;
    }


 //tcp线程
    task_5.pfnTaskEntry = (TSK_ENTRY_FUNC)wifi_process;
    task_5.uwStackSize = 10240;
    task_5.pcName = "wifi_process";
    task_5.usTaskPrio = 24;
    ret = LOS_TaskCreate(&thread_id_5, &task_5);
    if (ret != LOS_OK)
    {
        printf("Falied to create wifi_process ret:0x%x\n", ret);
        return;
    }

    //人体感应
    task_6.pfnTaskEntry = (TSK_ENTRY_FUNC)device_read_thraed;
    task_6.uwStackSize = 2048;
    task_6.pcName = "device read thraed";
    task_6.usTaskPrio = 24;
    ret = LOS_TaskCreate(&thread_id_6, &task_6);
    if (ret != LOS_OK)
    {
        printf("Falied to create task ret:0x%x\n", ret);
        return;
    }


}

APP_FEATURE_INIT(iot_smart_home_example);
